<template>
  <div ref="container"></div>
</template>

<script setup lang="ts">
import * as THREE from 'three'
import {RGBELoader} from 'three/examples/jsm/loaders/RGBELoader'
// 轨道控制器
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls'

import {onMounted, ref} from "vue";
import useWindowResize from "@/hook/useWindowResize";


const container = ref<HTMLElement>()

const camera = ref<THREE.PerspectiveCamera>()
const scene = ref<THREE.Scene>()
const controls = ref<OrbitControls>()
const renderer = ref<THREE.WebGLRenderer>()

const {width, height} = useWindowResize(213, 53, () => {
  if (camera.value) {
    camera.value.aspect = width!.value / height!.value // 更新相机宽高比
    camera.value.updateProjectionMatrix(); // 更新投影矩阵
    renderer.value!.setSize(width.value, height.value)
  }
})

onMounted(() => {
  initScene() // 场景初始化
  initCamera() // 初始化相机
  initRenderer() // 初始化渲染器
  initEnvMap() // 加载贴图
  initControls()// 初始化控制器
  animate()
})

const initScene = () => {
  scene.value = new THREE.Scene()
}

const initCamera = () => {
  camera.value = new THREE.PerspectiveCamera(45, width.value / height.value, 1, 200)
  camera.value?.position.set(5, 0.5, 5)
}

const initRenderer = () => {
  renderer.value = new THREE.WebGLRenderer({antialias: true})
  renderer.value?.setPixelRatio(window.devicePixelRatio) // 屏幕像素比
  renderer.value?.setSize(width.value, height.value) // 渲染尺寸
  renderer.value!.toneMapping = THREE.ACESFilmicToneMapping // 色调映射
  renderer.value!.toneMappingExposure = 2 // 曝光程度
  container.value?.appendChild(renderer.value!.domElement)
}

const initControls = () => {
  controls.value = new OrbitControls(camera.value!, renderer.value!.domElement)
  controls.value.enableZoom = true
  controls.value.autoRotate = true
}

const initEnvMap = () => {
  new RGBELoader().load('/cannon_1k.hdr', (texture: THREE.Texture) => {
    // 贴图设置球形的映射
    texture.mapping = THREE.EquirectangularReflectionMapping
    scene.value!.background = texture
    scene.value!.environment = texture
  })
}

const render = () => {
  renderer.value?.render(scene.value!, camera.value!)
  controls.value!.update()
}

const animate = () => {
  renderer.value?.setAnimationLoop(render)

}

</script>

<style scoped>

</style>
